﻿using System;
using System.Threading;
using System.Threading.Tasks;
using OpenFileTransfer.Wpf.Services;
using SuperSocket;
using SuperSocket.Channel;

namespace OpenFileTransfer.Wpf.WebSocketServer.Server
{
    public class MyMiddleware : MiddlewareBase
    {
        private ISessionContainer? _sessionContainer;
        private Task? _sendTask;

        private readonly CancellationTokenSource _tokenSource;

        private readonly ILogService _logService;
        private readonly int _heartBeatCheckInterval;
        private readonly int _heartBeatTimeout;

        public MyMiddleware(
            ILogService logService,
            IConfigService configService
        )
        {
            _logService = logService;
            _heartBeatCheckInterval = configService.WebSocketServerInfo.HeartBeatCheckInterval;
            _heartBeatTimeout = configService.WebSocketServerInfo.HeartBeatTimeout;
            _tokenSource = new CancellationTokenSource();
        }

        public override void Start(IServer server)
        {
            _logService.Info($@"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} Server Start.");
            _sessionContainer = server.GetSessionContainer();
            _sendTask = Task.Run(async () => await
                CheckTimeoutAsync(_tokenSource.Token, _heartBeatCheckInterval * 1000));
        }

        public override void Shutdown(IServer server)
        {
            _tokenSource.Cancel(false);
            _sendTask?.Wait();
            _logService.Info($@"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} Server Shutdown.");
        }

        private async Task CheckTimeoutAsync(CancellationToken token, int interval)
        {
            while (true)
            {
                try
                {
                    //超时等待
                    await Task.Delay(interval, token);
                }
                catch (Exception)
                {
                    break;
                }

                if (token.IsCancellationRequested || _sessionContainer == null)
                {
                    break;
                }

                try
                {
                    //统计超时
                    foreach (var session in _sessionContainer.GetSessions<MySession>())
                    {
                        var timeSpan = DateTime.Now - session.Info.LastActiveTime;
                        if (timeSpan.TotalSeconds >= _heartBeatTimeout)
                        {
                            await session.CloseAsync(CloseReason.TimeOut);
                        }
                    }
                }
                catch (Exception e)
                {
                    _logService?.Info($@"统计超时失败：{e.Message}.");
                }
            }
        }
    }
}
